/*
 * @Author: 周浪
 * @Date: 2023-07-03 09:23:25
 * @LastEditors: 周浪 z13647966598@163.com
 * @LastEditTime: 2023-08-07 17:53:12
 * @FilePath: \printing-component\src\electron-service\ipc\print.js
 */
import { ipcMain, BrowserWindow, dialog } from 'electron'
const { exec } = require('child_process')
export class Print {
  constructor(win) {
    /** 系统打印机对应的打印窗体数组 */
    this.browserWindowList = []
    /** 系统打印机任务队列 */
    this.queue = {}
    /** 主窗体的实例对象 */
    this.win = win
    /** 是否暂停 */
    this.isSuspend = false
    /** 错误枚举 */
    this.errorEnum = {
      'Unsupported pageSize': '纸张大小，打印机不支持，请修改打印机配置后继续打印。',
    }
    /** 主窗体退出，清空所有打印窗体 */
    this.win.on('close', (event) => {
      this.browserWindowList.forEach((f) => {
        f.browserWindow.close()
      })
    })
  }

  /**
   * @method 初始化打印窗体数组数据
   * @param list 打印机列表
   */
  setBrowserWindowList(list) {
    const listNames = list.map((m) => m.name)
    this.browserWindowList = this.browserWindowList.filter((f) => listNames.includes(f.name))
    list.forEach((m) => {
      this.queue[m.name] = this.queue[m.name] ? this.queue[m.name] : []
      if (!this.browserWindowList.find((f) => f.name === m.name)) {
        this.browserWindowList.push({
          ...m,
          browserWindow: new BrowserWindow({
            width: 1920,
            height: 1080,
            contextIsolation: false,
            enableRemoteModule: true,
            nodeIntegration: true,
            webSecurity: false,
            show: false,
          }),
        })
      }
    })
  }
  /**
   * @method 添加打印任务
   * @param task 任务
   */
  addQueue(name, task) {
    if (!this.queue[name]) {
      this.queue[name] = []
    }
    this.queue[name].push(task)

    if (this.queue[name].length === 1) {
      this.processQueue()
    }
  }
  /**
   * @method 处理不同的打印机的打印队列
   */
  async processQueue() {
    const keys = Object.keys(this.queue)
    keys.forEach((key) => {
      this.executeQueue(key)
    })
  }
  /**
   * @method 执行任务队列
   * @param key 执行任务的key
   */
  async executeQueue(key) {
    // 当前打印机队列为空或者暂停打印的状态
    if (!this.queue[key] || this.queue[key].length === 0 || this.isSuspend) {
      return
    }
    try {
      await this.queue[key][0]()
    } catch (error) {
      console.log('error.executeQueue', error.message)
    } finally {
      if (this.queue[key] && this.queue[key].length) {
        this.queue[key].shift()
        this.executeQueue(key)
      }
    }
  }
  /**
   * @method 打印任务
   * @param item 需要打印的数据
   */
  browserWindowLoadAndPrint(name, item) {
    return new Promise(async (resolve, reject) => {
      try {
        const browserWindowItem = this.browserWindowList.find((f) => f.name === item.printerName)
        await this.win.webContents.send('set_systemPrintTask', { type: 'update', name, item: { printId: item.printId, printStatusName: '打印中' } })
        await this.delay(500)
        await browserWindowItem.browserWindow.loadURL('data:text/html,' + encodeURIComponent(item.htmlText))
        const systemConfig = await this.getPrinterPreferences(item.printerName)
        browserWindowItem.browserWindow.webContents.print({ deviceName: item.printerName, silent: true, landscape: systemConfig.Orientation === '2' ? true : false, color: systemConfig.Color === '2' ? true : false }, async (success, failureReason) => {
          await this.win.webContents.send('set_systemPrintTask', { type: 'update', name, item: { printId: item.printId, printStatusName: '打印完成' } })
          await this.delay(500)
          await this.win.webContents.send('set_systemPrintTask', { type: 'delete', name, item })
          resolve()
        })
        // await this.delay(5000)
        // await this.win.webContents.send('set_systemPrintTask', {
        //   type: 'update',
        //   name,
        //   item: {
        //     printId: item.printId,
        //     printStatusName: '打印完成',
        //   },
        // })
        // await this.win.webContents.send('set_systemPrintTask', {
        //   type: 'delete',
        //   name,
        //   item,
        // })
        // resolve()
      } catch (error) {
        console.log('error.browserWindowLoadAndPrint', error.message)
        this.isSuspend = true
        this.win.webContents.send('set_systemPrintTask', { type: 'update', name, item: { printId: item.printId, printStatusName: '打印失败' } })
        this.win.webContents.send('set_isSuspend', this.isSuspend)
        const keyList = Object.keys(this.errorEnum)
        const item = keyList.find((f) => error.message.indexOf(f) !== -1)
        if (item) {
          dialog.showErrorBox('打印出错', this.errorEnum[item])
        } else {
          dialog.showErrorBox('打印出错', '请检查打印机是否可用，以及打印首选项配置是否正确!')
        }
      }
    })
  }
  /**
   * @method 接受的socket数据推送到打印队列
   * @param list 需要打印的数据
   */
  initRequestData(list) {
    if (Array.isArray(list)) {
      list.forEach((f) => {
        const printItem = this.browserWindowList.find((b) => b.name === f.printerName)
        if (printItem) {
          this.win.webContents.send('set_systemPrintTask', {
            type: 'push',
            name: printItem.name,
            item: f,
          })

          let timeOut = setTimeout(() => {
            this.addQueue(printItem.name, () => {
              return this.browserWindowLoadAndPrint(printItem.name, f)
            })
            clearTimeout(timeOut)
          })
        }
      })
    }
  }
  /**
   * @method 控制打印队列暂停
   */
  suspendChange() {
    this.isSuspend = !this.isSuspend
    this.processQueue()
  }
  /**
   * @method 删除打印队列
   */
  queueClearAll() {
    this.queue = {}
    this.win.webContents.send('set_systemPrintTask', { type: 'deleteAll' })
  }

  async delay(ms) {
    await new Promise((resolve) => setTimeout(resolve, ms))
  }

  /**
   * @method 使用wmic命令获取到系统的打印机首选项的参数
   */
  getPrinterPreferences(printerName) {
    return new Promise((resolve, reject) => {
      const command = `wmic printerconfig where "DeviceName='${printerName}'" get Color,Orientation /format:csv`
      exec(command, (error, stdout, stderr) => {
        if (error) {
          reject(new Error(`获取系统打印机 ${printerName} 配置错误，请检查打印机是否可用!`))
          return
        }
        try {
          const lines = stdout.trim().split('\n')
          const header = lines[0].split(',')
          const values = lines[1].split(',')
          const printerPreferences = {}
          for (let i = 0; i < header.length; i++) {
            const key = header[i].trim()
            const value = values[i].trim()
            printerPreferences[key] = value
          }
          resolve(printerPreferences)
        } catch (error) {
          reject(new Error(`获取系统打印机 ${printerName} 配置错误，请检查打印机是否可用!`))
          return
        }
      })
    })
  }
}
